<?php

use Illuminate\Database\Capsule\Manager as DB;
use PhpOffice\PhpSpreadsheet\IOFactory;
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;

#[订单中心]
class OrderController extends AcommonController
{

    public function init()
    {
        $this->model      = new orderModel();
        $this->table      = 'order';
        $this->primaryKey = 'id';
        parent::init();
    }

    public function indexAction($returnData = FALSE)
    {
        if ($this->isPost()) {
            $this->appends = ['status_code', 'status_name'];
            $this->model   = $this->model->with(['member', 'customer', 'item']);
            $start_on      = $this->get('start_on');
            if (!empty($start_on)) {
                array_push($this->condition, ['created_at', '>=', $start_on]);
            }
            $end_on = $this->get('end_on');
            if (!empty($end_on)) {
                array_push($this->condition, ['created_at', '<=', $end_on]);
            }
            $mode = $this->get('mode');
            switch ($mode) {
                case 'canceled':
                    $this->model = $this->model->where('status', orderModel::STATUS_CANCEL);
                    break;
                case 'closed':
                    $this->model = $this->model->where('status', orderModel::STATUS_INVALID);
                    break;
                case 'nopay':
                    $this->model = $this->model->where('status', orderModel::STATUS_NOPAY);
                    break;
                case 'paid':
                    $this->model = $this->model->where('status', orderModel::STATUS_PAYED);
                    break;
                case 'nosend':
                    $this->model = $this->model->where('status', orderModel::STATUS_PAYED)->whereExists(function ($query) {
                        $query->from('order_item')->whereColumn('order_item.order_id', 'order.id')
                            ->where('dispatch_status', orderitemModel::DISPATCH_STATUS_NOSEND)
                            ->whereNotIn('refund_status', [orderitemModel::REFUND_STATUS_OK, orderitemModel::REFUND_STATUS_FINISH])
                            ->whereNotIn('aftersale_status', [orderitemModel::AFTERSALE_STATUS_AFTERING, orderitemModel::AFTERSALE_STATUS_OK]);
                    });
                    break;
                case 'send':
                    $this->model = $this->model->where('status', orderModel::STATUS_PAYED)->whereExists(function ($query) {
                        $query->from('order_item')->whereColumn('order_item.order_id', 'order.id')
                            ->where('dispatch_status', orderitemModel::DISPATCH_STATUS_SENDED)
                            ->whereNotIn('refund_status', [orderitemModel::REFUND_STATUS_OK, orderitemModel::REFUND_STATUS_FINISH])
                            ->whereNotIn('aftersale_status', [orderitemModel::AFTERSALE_STATUS_AFTERING, orderitemModel::AFTERSALE_STATUS_OK]);
                    });
                    break;
                case 'nocomment':
                    $this->model = $this->model->where('status', orderModel::STATUS_PAYED)->whereExists(function ($query) {
                        $query->from('order_item')->whereColumn('order_item.order_id', 'order.id')
                            ->where('dispatch_status', orderitemModel::DISPATCH_STATUS_GETED)
                            ->where('comment_status', orderitemModel::COMMENT_STATUS_NO)
                            ->whereNotIn('refund_status', [orderitemModel::REFUND_STATUS_OK, orderitemModel::REFUND_STATUS_FINISH])
                            ->whereNotIn('aftersale_status', [orderitemModel::AFTERSALE_STATUS_AFTERING, orderitemModel::AFTERSALE_STATUS_OK]);
                    });
                    break;
                case 'finished':
                    $this->model = $this->model->where('status', orderModel::STATUS_FINISH);
                    break;
                case 'aftersale':
                    $this->model = $this->model->where('status', orderModel::STATUS_PAYED)->whereExists(function ($query) {
                        $query->from('order_item')->whereColumn('order_item.order_id', 'order.id')
                            ->where('aftersale_status', '<>', orderitemModel::AFTERSALE_STATUS_NOAFTER);
                    });
                    break;
                case 'refund':
                    $this->model = $this->model->where('status', orderModel::STATUS_PAYED)->whereExists(function ($query) {
                        $query->from('order_item')->whereColumn('order_item.order_id', 'order.id')
                            ->where('refund_status', '<>', orderitemModel::REFUND_STATUS_NOREFUND);
                    });
                    break;
            }
            $keywordsType = $this->get('keywordsType');
            $keywords     = $this->get('keywords');
            if ($keywords !== '') {
                switch ($keywordsType) {
                    case 'order_id':
                        $this->model = $this->model->where('id', $keywords);
                        break;
                    case 'order_sn':
                        $this->model = $this->model->where('order_sn', 'like', "%{$keywords}%");
                        break;
                    case 'member_id':
                        $this->model = $this->model->where('member_id', $keywords);
                        break;
                    case 'member_phone':
                        $this->model = $this->model->whereIn('member_id', DB::table('member')->where('phone', 'like', "%{$keywords}%")->limit(20)->pluck('id'));
                        break;
                    case 'customer_id':
                        $this->model = $this->model->where('customer_id', $keywords);
                        break;
                    case 'consignee':
                        $this->model = $this->model->where('consignee', $keywords);
                        break;
                    case 'consignee_phone':
                        $this->model = $this->model->where('phone', 'like', "%{$keywords}%");
                        break;
                }
            }
            $payType = $this->get('payType');
            if ($payType !== '') {
                $this->model = $this->model->where('pay_type', $payType);
            }
            $goods = $this->get('goods');
            if ($goods !== '') {
                if (is_numeric($goods)) {
                    $this->model = $this->model->whereExists(function ($query) use ($goods) {
                        $query->from('order_item')->whereColumn('order_item.order_id', 'order.id')->where('goods_id', $goods);
                    });
                } else {
                    $this->model = $this->model->whereExists(function ($query) use ($goods) {
                        $query->from('order_item')->whereColumn('order_item.order_id', 'order.id')
                            ->whereIn('goods_id', DB::table('goods')->where('title', 'like', "%{$goods}%")->limit(20)->pluck('id'));
                    });
                }
            }
            $dataset = parent::indexAction(TRUE);
            foreach ($dataset['rows'] as $k1 => &$v1) {
                if($v1['ext']){
                    $ext = json_decode($v1['ext'], true);
                    if($ext['combo']==1){
                        $v1['combo_goods_id'] = $v1['item'][0]['goods_id'];
                        $v1['combo_goods_title'] = $v1['item'][0]['goods_title'];
                    }
                }
                foreach ($v1['item'] as $k2 => $v2) {
                    if ($v2['goods_combo']) {
                        $combo = json_decode($v2['goods_combo'], true);
                        if($combo['goods']) {
                            foreach ($combo['goods'] as $k3 => &$v3) {
                                $v3['status_code']      = $v3['status_code'] ?? $v2['status_code'];
                                $v3['refund_status']    = $v3['refund_status'] ?? 0;
                                $v3['aftersale_status'] = $v3['aftersale_status'] ?? 0;
                            }
                            $v1['item'] = $combo['goods'] ?? [];
                        }
                    }
                }
            }
            json($dataset);
        } else {
            parent::indexAction();
        }
    }

    public function editAction()
    {
        if (!$this->isPost()) {
            $query   = $this->model->with(['member', 'customer', 'item']);
            $this->appends = ['status_desc', 'status_code', 'abtns', 'ext_arr'];
            $this->_view->assign('packageList', orderexpressModel::with(['log', 'order'])->where('order_id', $this->get('id'))->get()->toJson());

            $id	= $this->get($this->primaryKey, 0);
            if($query->where($this->primaryKey,'=',$id)->doesntExist()){
                throw new Exception("记录不存在");
            }
            $query = $query->where($this->primaryKey,'=',$id)->first();
            if(!empty($this->appends)){
                foreach ($this->appends as $append){
                    $query = $query->append($append);
                }
            }
            $dataset = $query->toArray();
            if(isset($dataset['ext_arr']['combo']) && $dataset['ext_arr']['combo']==1) {
                foreach ($dataset['item'] as $v2) {
                    if ($v2['goods_combo']) {
                        $combo           = json_decode($v2['goods_combo'], true);
                        $dataset['item']     = $combo['goods'];
                        break;
                    }
                }
            }
            $this->_view->assign('dataset', json_encode($dataset));
            $this->_view->display( strtolower($this->controller) . '/edit.html');

        } else {
            parent::editAction();
        }
    }

    #[添加备注]
    public function memoAction()
    {
        if (!$this->isPost()) {
            $this->_view->assign('content', json_encode(orderModel::where('id', $this->get('order_id'))->value('memo')));
            $this->_view->display( strtolower($this->controller) . '/memo.html');
        }else {
            $order = $this->get('order');
            $rows  = [
                'id'   => $order['id'],
                'memo' => $this->get('memo')
            ];
            $roles = [
                'id'   => ['role' => "required|exists:order.id", 'msg' => '订单'],
                'memo' => ['role' => "required", 'msg' => '备注'],
            ];
            Validate::check($rows, $roles);
            $memo = $rows['memo'];
            try {
                DB::beginTransaction();
                orderactionModel::operAdd($order, null, ['id' => $this->auth->user_id], 'admin', $rows['memo']);
                orderModel::where('id', $order['id'])->update(['memo' => $memo]);
                DB::commit();
                $result = [
                    'ret'  => 0,
                    'msg'  => '操作成功',
                    'data' => $memo
                ];
            } catch (Exception $e) {
                DB::rollBack();
                $result = [
                    'ret' => 30001,
                    'msg' => $e->getMessage(),
                ];
            }
            json($result);
        }
    }

    #[订单发货]
    public function deliveryAction()
    {
        if ($this->isPost()) {
            $params = $this->postData;
            do {
                $roles = [
                    'items'     => ['role' => "required", 'msg' => '发货商品'],
                    'member_id' => ['role' => "required|exists:member.id", 'msg' => '会员'],
                    'order_id'  => ['role' => "required|exists:order.id", 'msg' => '订单'],
                ];
                Validate::check($params, $roles);
                if (empty($params['express_code']) || empty($params['express_no'])) {
                    $result = [
                        'ret' => 30002,
                        'msg' => '快递公司与单号不能为空',
                    ];
                    break;
                }
                try {
                    DB::beginTransaction();
                    $order                = orderModel::find($params['order_id']);
                    $ext_arr              = $order->ext_arr;
                    $ext_arr['send_time'] = time();
                    $order->ext           = json_encode($ext_arr);
                    $order->updated_at    = date('Y-m-d H:i:s');
                    $order->save();

                    $express         = expressModel::where('code', $params['express_code'])->first();
                    $orderexpressRow = [
                        'member_id'    => $params['member_id'],
                        'order_id'     => $params['order_id'],
                        'express_name' => $express->name,
                        'express_code' => $express->code,
                        'express_no'   => $params['express_no'],
                        'created_at'   => date('Y-m-d H:i:s')
                    ];
                    if($params['id']>0){
                        orderexpressModel::where('id', $params['id'])->update($orderexpressRow);
                        $express_id = $params['id'];
                    }else{
                        $express_id = orderexpressModel::insertGetId($orderexpressRow);
                    }
                    // 发货后自动订阅快递鸟物流追踪
                    \Queue::push('\app\job\OrderSend@subscribe', ['express_id' => $express_id], 'shop');

                    if (isset($ext_arr['combo']) && $ext_arr['combo'] == 1) {
                        // 套餐订单商品发货处理
                        $orderItem  = orderitemModel::where('order_id', $params['order_id'])->first();
                        $goods_combo      = $orderItem->goods_combo;
                        if(empty($goods_combo)){
                            throw new Exception('套餐商品数据异常');
                        }
                        $combo      = json_decode($goods_combo);
                        $is_allDelivery = true;
                        foreach ($combo->goods as &$item) {
                            if(in_array($item->goods_sku_price_id, $params['items'])) {
                                $item->dispatch_status = 1;
                                $item->express_name    = $express->name;
                                $item->express_code    = $express->code;
                                $item->express_no      = $params['express_no'];
                                $item->ext             = json_encode(['send_time' => time()]);
                            }
                            if($item->dispatch_status==0){
                                $is_allDelivery = false;
                            }
                        }
                        $orderItem->goods_combo          = json_encode($combo);
                        if($is_allDelivery) {
                            // 若商品已全部发货, 则更新主Item为已发货状态
                            $orderItem->dispatch_status = 1;
                            $orderItem->express_name    = $express->name;
                            $orderItem->express_code    = $express->code;
                            $orderItem->express_no      = $params['express_no'];
                            $ext_arr                    = $orderItem->ext_arr;
                            $ext_arr['send_time']       = time();
                            $orderItem->ext             = json_encode($ext_arr);
                        }
                        $orderItem->updated_at           = date('Y-m-d H:i:s');
                        $orderItem->save();
                    } else {
                        foreach ($params['items'] as $item) {
                            $orderItem                       = orderitemModel::where('order_id', $params['order_id'])->where('goods_sku_price_id', $item)->first();
                            $orderItem->dispatch_status      = 1;
                            $orderItem->express_name         = $express->name;
                            $orderItem->express_code         = $express->code;
                            $orderItem->express_no           = $params['express_no'];
                            $ext_arr                         = $orderItem->ext_arr;
                            $ext_arr['send_time']            = time();
                            $orderItem->ext                  = json_encode($ext_arr);
                            $orderItem->updated_at           = date('Y-m-d H:i:s');
                            $orderItem->save();
                        }
                    }

                    DB::commit();
                    foreach ($params['items'] as $item) {
                        \Hook::emit('order_send_after', ['item' => orderitemModel::where('order_id', $params['order_id'])->where('goods_sku_price_id', $item)->first()]);
                    }
                    $result = [
                        'ret' => 0,
                        'msg' => '操作成功'
                    ];
                } catch (Exception $e) {
                    DB::rollBack();
                    $result = [
                        'ret' => 30001,
                        'msg' => $e->getMessage(),
                    ];
                }
            } while (FALSE);

            json($result);
        } else {
            $express_id = $this->get('express_id');
            if($express_id){
                $express = orderexpressModel::find($express_id);
                $dataset = orderModel::with('item')->find($express->order_id)->append('ext_arr')->toArray();
                if($dataset['ext_arr']['combo']==1){
                    $combo           = json_decode($dataset['item'][0]['goods_combo'], true);
                    $dataset['item'] = $combo['goods'];
                }
                $items = [];
                foreach ($dataset['item'] as $v2) {
                    if($v2['express_no']==$express->express_no){
                        $items[] = $v2['goods_sku_price_id'];
                    }
                }
                $express->items = $items;
                $this->_view->assign('express', $express->toJson());
            }else {
                $dataset = orderModel::with('item')->find($this->get('order_id'))->append('ext_arr')->toArray();
                if(isset($dataset['ext_arr']['combo']) && $dataset['ext_arr']['combo']==1){
                    $combo           = json_decode($dataset['item'][0]['goods_combo'], true);
                    $dataset['item'] = $combo['goods'];
                }
                $this->_view->assign('express', json_encode([
                    'member_id'     => '',
                    'items'         => [],
                    'order_id'      => $this->get('order_id'),
                    'express_name'  => '',
                    'express_code'  => '',
                    'express_no'    => '',
                ]));
            }
            $this->_view->assign('dataset', json_encode($dataset));
            $this->_view->display(strtolower($this->controller) . '/delivery.html');
        }
    }

    #[收货地址更新]
    public function consigneeAction()
    {
        if ($this->isPost()) {
            $params = $this->postData;
            do {
                $order = orderModel::find($params['id']);
                $order->consignee = $params['consignee'];
                $order->phone = $params['phone'];
                $order->province_id = $params['province_id'];
                $order->city_id = $params['city_id'];
                $order->area_id = $params['area_id'];
                $order->address = $params['address'];

                $area = DB::table('area')
                    ->where('id',  $this->postData['province_id'])
                    ->orWhere('id',$this->postData['city_id'])
                    ->orWhere('id',$this->postData['area_id'])
                    ->pluck('name', 'id');
                $order->province_name = $area[$this->postData['province_id']];
                $order->city_name = $area[$this->postData['city_id']];
                $order->area_name = $area[$this->postData['area_id']];
                $order->save();
            }while(FALSE);
            ret(0, '地址更新成功', $order);
        }else{
            $prov = DB::table('area')->where('level', 1)->get();
            $city = DB::table('area')->where('level', 2)->get();
            $area = DB::table('area')->where('level', 3)->get();
            $this->_view->assign('prov', $prov->toJson());
            $this->_view->assign('city', $city->toJson());
            $this->_view->assign('area', $area->toJson());

            $order_id = $this->get('order_id');
            $order = orderModel::find($order_id);
            $this->_view->assign('dataset', $order->toJson());
            $this->_view->display(strtolower($this->controller) . '/consignee.html');
        }
    }

    #[批量发货]
    public function batchsendAction()
    {
        if ($this->isPost()) {
            $inputs = $this->postData;
            do {
                $roles = [
                    'uploadFile' => ['role' => "required", 'msg' => '发货表单'],
                    'express_id' => ['role' => "required|exists:express.id", 'msg' => '快递公司'],
                ];
                Validate::check($inputs, $roles);
                try {
                    $data = $this->importing($inputs['uploadFile']);
                    DB::beginTransaction();
                    foreach ($data as $k => $v) {
                        $express_no = $v['V'];
                        if (empty($express_no)) {
                            continue;
                        }
                        $order           = orderModel::find($v['A']);
                        $ext_arr         = $order->ext_arr;
                        $orderItem       = orderitemModel::find($v['C']);
                        $express         = expressModel::find($inputs['express_id']);
                        $orderexpressRow = [
                            'member_id'    => $orderItem->member_id,
                            'order_id'     => $orderItem->order_id,
                            'express_name' => $express->name,
                            'express_code' => $express->code,
                            'express_no'   => $express_no,
                            'created_at'   => date('Y-m-d H:i:s')
                        ];
                        $express_id = orderexpressModel::insertGetId($orderexpressRow);

                        // 发货后自动订阅快递鸟物流追踪
                        \Queue::push('\app\job\OrderSend@subscribe', ['express_id' => $express_id], 'shop');

                        if (isset($ext_arr['combo']) && $ext_arr['combo'] == 1) {
                            // 套餐订单商品发货处理
                            $goods_combo      = $orderItem->goods_combo;
                            if(empty($goods_combo)){
                                continue;
                            }
                            $combo      = json_decode($goods_combo);
                            $is_allDelivery = true;
                            foreach ($combo->goods as &$item) {
                                $item->dispatch_status = 1;
                                $item->express_name    = $express->name;
                                $item->express_code    = $express->code;
                                $item->express_no      = $express_no;
                                $item->ext             = json_encode(['send_time' => time()]);
                            }
                            $orderItem->goods_combo          = json_encode($combo);
                            if($is_allDelivery) {
                                // 若商品已全部发货, 则更新主Item为已发货状态
                                $orderItem->dispatch_status = 1;
                                $orderItem->express_name    = $express->name;
                                $orderItem->express_code    = $express->code;
                                $orderItem->express_no      = $express_no;
                                $ext_arr                    = $orderItem->ext_arr;
                                $ext_arr['send_time']       = time();
                                $orderItem->ext             = json_encode($ext_arr);
                            }
                            $orderItem->updated_at           = date('Y-m-d H:i:s');
                            $orderItem->save();
                        } else {
                            $orderItem->dispatch_status      = 1;
                            $orderItem->express_name         = $express->name;
                            $orderItem->express_code         = $express->code;
                            $orderItem->express_no           = $express_no;
                            $orderItem->ext_arr['send_time'] = time();
                            $ext_arr                         = $orderItem->ext_arr;
                            $ext_arr['send_time']            = time();
                            $orderItem->ext                  = json_encode($ext_arr);
                            $orderItem->updated_at           = date('Y-m-d H:i:s');
                            $orderItem->save();
                        }

                        $ext_arr['send_time'] = time();
                        $order->ext           = json_encode($ext_arr);
                        $order->updated_at    = date('Y-m-d H:i:s');
                        $order->save();

                        \Hook::emit('order_send_after', ['item' => orderitemModel::find($v['C'])]);
                    }
                    DB::commit();
                    $result = [
                        'ret' => 0,
                        'msg' => '操作成功'
                    ];
                } catch (Exception $e) {
                    DB::rollBack();
                    $result = [
                        'ret' => 30001,
                        'msg' => $e->getMessage(),
                    ];
                }
            } while (FALSE);

            json($result);
        } else {
            $this->_view->display(strtolower($this->controller) . '/batchsend.html');
        }
    }
    
    #[更新物流]
    public function getExpressAction()
    {
        $express_id = $this->get('express_id');

        // 获取包裹
        $orderExpress = orderexpressModel::with('order')->where('id', $express_id)->first();
        if (!$orderExpress) {
            ret(30001, '包裹不存在');
        }

        $expressLib = new app\service\express;
        try {
            // 手动查询
            $result = $expressLib->search([
                'express_code' => $orderExpress['express_code'],
                'express_no'   => $orderExpress['express_no']
            ], $orderExpress, $orderExpress->order);

            // 差异更新物流信息
            $expressLib->checkAndAddTraces($orderExpress, $result);

            $packageList = orderexpressModel::with(['log', 'order'])->where('order_id', $orderExpress->order_id)->get();
        } catch (\Exception $e) {
            ret(30002, '更新失败'.$e->getMessage());
        }

        ret(0, '刷新成功', $packageList);
    }

    #[订阅物流]
    public function subExpressAction()
    {
        $express_id = $this->get('express_id');

        // 获取包裹
        $orderExpress = orderexpressModel::with('order')->where('id', $express_id)->first();
        if (!$orderExpress) {
            ret(30001, '包裹不存在');
        }

        $expressLib = new app\service\express;
        try {
            // 手动查询
            $result = $expressLib->subscribe([
                'express_code' => $orderExpress['express_code'],
                'express_no'   => $orderExpress['express_no']
            ], $orderExpress, $orderExpress->order);
        } catch (\Exception $e) {
            ret(30002, '订阅失败'.$e->getMessage());
        }

        ret(0, '订阅成功', $result);
    }

    private function importing($file, $sheet = 0, $jumpTo = 2)
    {
        try {
            //$file = iconv("utf-8", "gb2312", $file);
            $file = APP_PATH . '/public/excel/' . $file;
            if (!file_exists($file)) {
                $filepath = 'http://files.zmssp.cn/excel/' . $file;
                file_put_contents($file, file_get_contents($filepath));
                if (!file_exists($file)) {
                    throw new \Exception('文件不存在!');
                }
            }
            $objRead = IOFactory::createReader('Xlsx');
            if (!$objRead->canRead($file)) {
                $objRead = IOFactory::createReader('Xls');
                if (!$objRead->canRead($file)) {
                    throw new \Exception('只支持导入Excel文件！');
                }
            }
            $objRead->setReadDataOnly(true);
            $obj = $objRead->load($file);

            /* 获取指定的sheet表 */
            $currSheet = $obj->getSheet($sheet);

            if (isset($options['mergeCells'])) {
                /* 读取合并行列 */
                $options['mergeCells'] = $currSheet->getMergeCells();
            }
            /* 取得最大的列号 */
            $columnH = $currSheet->getHighestColumn();
            /* 兼容原逻辑，循环时使用的是小于等于 */
            $columnCnt = Coordinate::columnIndexFromString($columnH);

            /* 获取总行数 */
            $rowCnt = $currSheet->getHighestRow();
            $data   = [];

            /* 读取内容 */
            for ($_row = $jumpTo; $_row <= $rowCnt; $_row++) {
                $isNull = true;

                for ($_column = 1; $_column <= $columnCnt; $_column++) {
                    $cellName = Coordinate::stringFromColumnIndex($_column);
                    $cellId   = $cellName . $_row;
                    $cell     = $currSheet->getCell($cellId);

                    if (isset($options['format'])) {
                        /* 获取格式 */
                        $format = $cell->getStyle()->getNumberFormat()->getFormatCode();
                        /* 记录格式 */
                        $options['format'][$_row][$cellName] = $format;
                    }

                    $data[$_row][$cellName] = trim($currSheet->getCell($cellId)->getFormattedValue());

                    if (!empty($data[$_row][$cellName])) {
                        $isNull = false;
                    }
                }

                if ($isNull) {
                    unset($data[$_row]);
                }
            }
            return $data;
        } catch (\Exception $e) {
            dump($e->getMessage());
        }
    }

    #[上传文件]
    public function uploadbatchfileAction()
    {
        $files = $this->getFiles('file');
        if ($files != NULL && $files['size'] > 0) {
            $uploader = new FileUploader();
            $files    = $uploader->getFile('file');
            if (!$files) {
                ret(30001, '文件异常');
            }
            if ($files->getSize() == 0) {
                ret(30002, '文件大小异常');
            }
            if (!$files->checkExts('xls,xlsx')) {
                ret(30003, '文件类型异常');
            }
            if (!$files->checkSize(20000000)) {
                ret(30004, '文件大小超限');
            }

            $dirpath = APP_PATH . '/public/excel/';
            if ($dirpath !== '.' && !file_exists($dirpath)) {
                mkdir($dirpath, 0777, true);
            }
            $filename = 'batchexcel' . date('Ymd') . uniqid() . $files->getExt();
            $filepath = $dirpath . $filename;
            if ($files->move($filepath)) {
                $postData = [
                    'token'     => md5($filepath . ENCRYPT_IV),
                    'file_path' => $filepath,
                    'file_body' => base64_encode(file_get_contents($dirpath . $filename))
                ];
                $res = json_decode(request('http://files.zmssp.cn/files/upload', $postData), true);
                if($res['ret']==0){
                    ret(0, '文件上传成功', $filename);
                }
            }
        }
        ret(30005, '文件上传失败');
    }

    #[快递公司]
    public function expressAction()
    {
        $query = new expressModel();
        $total = $query->count();
        $sort  = $this->get('sort', 'weigh');
        $order = $this->get('order', 'desc');
        $query = $query->orderBy($sort, $order)->orderBy('code', 'ASC');
        $page  = $this->get('page');
        if (!empty($page)) {
            $limit  = $this->get('rows', 10);
            $offset = ($page - 1) * $limit;
            $query  = $query->offset($offset)->limit($limit);
        }
        $rows = $query->get();
        json(['total' => $total, 'rows' => $rows]);
    }

    #[订单退款]
    public function refundAction()
    {
        $params = $this->postData;
        do {
            $roles = [
                'order_id'      => ['role' => "required|exists:order.id", 'msg' => '订单'],
                'order_item_id' => ['role' => "exists:order_item.id", 'msg' => '订单商品'],
                'money'         => ['role' => "required|gte:0", 'func' => "isPrice", 'msg' => '退款金额'],
            ];
            Validate::check($params, $roles);
            $refund_money = round($params['money'], 2);
            if ($refund_money < 0) {
                $result = [
                    'ret' => 30003,
                    'msg' => '退款金额不能小于 0',
                ];
                break;
            }

            $order = $this->model->whereIn('status',
                [
                    orderModel::STATUS_PAYED,
                    orderModel::STATUS_FINISH
                ]
            )->with('item')->where('id', $params['order_id'])->first();
            if (!$order) {
                $result = [
                    'ret' => 30004,
                    'msg' => '订单不存在或不可退款',
                ];
                break;
            }

            $items = $order->item;
            $items = array_column($items->toArray(), null, 'id');

            // 当前订单已退款总金额
            $refunded_money = array_sum(array_column($items, 'refund_fee'));
            // 剩余可退款金额
            $refund_surplus_money = $order->pay_fee - $refunded_money;
            // 如果退款金额大于订单支付总金额
            if ($refund_money > $refund_surplus_money) {
                $result = [
                    'ret' => 30005,
                    'msg' => '退款总金额不能大于实际支付金额',
                ];
                break;
            }

            if (isset($params['order_item_id']) && $params['order_item_id'] > 0) {
                $item = $items[$params['order_item_id']];
                if (!$item || in_array($item['refund_status'], [
                        orderitemModel::REFUND_STATUS_OK,
                        orderitemModel::REFUND_STATUS_FINISH,
                    ])) {
                    $result = [
                        'ret' => 30006,
                        'msg' => '订单商品已退款，不能重复退款',
                    ];
                    break;
                }
            } else {
                $is_refund = false;
                foreach ($items as $key => $it) {
                    if (in_array($it['refund_status'], [
                        orderitemModel::REFUND_STATUS_OK,
                        orderitemModel::REFUND_STATUS_FINISH,
                    ])) {
                        // 已退款
                        unset($items[$key]);
                    } else {
                        $is_refund = true;
                    }
                }
                $items = array_values($items);

                if (!$is_refund) {
                    $result = [
                        'ret' => 30006,
                        'msg' => '订单商品已退款，不能重复退款',
                    ];
                    break;
                }
            }
            $item_id = $params['order_item_id'] ?? null;
            DB::transaction(function () use ($order, $items, $item_id, $refund_money, $refund_surplus_money) {
                if ($item_id) {
                    // 单个商品退款
                    $item = $items[$item_id];
                    orderModel::startRefund($order, $item, $refund_money, ['id' => $this->auth->user_id], '管理员操作退款, 订单编号:'.$order->order_sn);
                } else {
                    // 全部退款
                    // 未退款 item 商品总金额
                    $goods_total_amount = 0;
                    foreach ($items as $ke => $it) {
                        $goods_total_amount += ($it['goods_price'] * $it['goods_num']);
                    }

                    $current_refunded_money = 0;
                    for ($i = 0; $i < count($items); $i++) {
                        if ($i == (count($items) - 1)) {
                            // 最后一条,全部退完
                            $current_refund_money = $refund_money - $current_refunded_money;
                        } else {
                            // 按比例计算当前 item 应退金额
                            $current_refund_money = round($refund_money * (($items[$i]['goods_price'] * $it['goods_num']) / $goods_total_amount), 2);
                        }
                        if (($current_refunded_money + $current_refund_money) > $refund_money) {
                            $current_refund_money = $refund_money - $current_refunded_money;
                        }

                        if ($current_refund_money >= 0) {       // 支付金额或者退款金额 为 0 也能退
                            $current_refunded_money += $current_refund_money;

                            orderModel::startRefund($order, $items[$i], $current_refund_money, ['id' => $this->auth->user_id], '管理员操作退款, 订单编号:'.$order->order_sn);
                        }
                    }
                }
            });

            $result = [
                'ret' => 0,
                'msg' => '操作成功'
            ];
        } while (FALSE);

        json($result);
    }

    #[订单导出]
    public function exportAction()
    {
        $type     = $this->get('keywordsType');
        $keywords = $this->get('keywords');
        $startOn  = $this->get('start_on');
        $endOn    = $this->get('end_on');
        $mode     = $this->get('mode');
        $goods    = $this->get('goods');

        $dirpath = APP_PATH . '/public/excel/';
        if ($dirpath !== '.' && !file_exists($dirpath)) {
            mkdir($dirpath, 0777, true);
        }
        $filename = 'order' . date('Ymd') . uniqid() . '.xlsx';
        $filepath = $dirpath . $filename;
        $res      = exec("php " . APP_PATH . "/public/cli.php export/order \"type={$type}&keywords={$keywords}&startOn={$startOn}&endOn={$endOn}&mode={$mode}&goods={$goods}&path={$filepath}\"");
        if ($res === 'Done' && file_exists($dirpath . $filename)) {
            if( $webpath = syncFile($filepath) ){
                ret(0, '订单导出excel成功', $webpath);
            }
        }
        ret(30003, '订单导出失败');
    }

    #[待发货订单导出]
    public function exportnosendAction()
    {
        $type     = $this->get('keywordsType');
        $keywords = $this->get('keywords');
        $startOn  = $this->get('start_on');
        $endOn    = $this->get('end_on');
        $mode     = $this->get('mode');
        $goods    = $this->get('goods');

        $dirpath = APP_PATH . '/public/excel/';
        if ($dirpath !== '.' && !file_exists($dirpath)) {
            mkdir($dirpath, 0777, true);
        }
        $filename = 'ordernosend' . date('Ymd') . uniqid() . '.xlsx';
        $filepath = $dirpath . $filename;
        $res      = exec("php " . APP_PATH . "/public/cli.php export/ordernosend \"type={$type}&keywords={$keywords}&startOn={$startOn}&endOn={$endOn}&goods={$goods}&path={$filepath}\"");
        if ($res === 'Done' && file_exists($dirpath . $filename)) {
			if( $webpath = syncFile($filepath) ){
                ret(0, '发货单导出excel成功', $webpath);
            }
        }
        ret(30003, '订单导出失败');
    }

}
